package com.thy.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.common.dto.stat.module.DoctorStatDto;
import com.hospital.common.dto.stat.module.StatDto;
import com.hospital.common.pojo.TStat;
import com.hospital.common.vo.stat.module.DoctorStatVo;
import com.hospital.common.vo.stat.module.StatVo;
import com.thy.mapper.TStatMapper;
import com.thy.properties.CaseConfigProperties;
import com.thy.service.TStatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 统计表 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-09-13
 */
@Service
public class TStatServiceImpl extends ServiceImpl<TStatMapper, TStat> implements TStatService {

    @Autowired
    private TStatMapper statMapper;
    @Autowired
    private CaseConfigProperties caseConfigProperties;
    @Override
    public  void allStat(StatDto statDto) {
       //查询每个科室的患者总数
        List<Map<String, Object>> totalRegistrationsList = statMapper.getTotalRegistrations(statDto);
        //退号患者数
        List<Map<String, Object>> cancellationsList = statMapper.getCancellations(statDto);
        //Ai诊疗记录数
        List<Map<String, Object>> aiConsultCountsList = statMapper.getAiConsultCount(statDto);
        //总诊疗记录数
        List<Map<String, Object>> totalConsultCountsList = statMapper.getTotalConsultCount(statDto);
        //采纳数
        List<Map<String, Object>> aiDiagnosisAcceptanceList = statMapper.getAiDiagnosisAcceptancePct(statDto);
        //投诉数
        List<Map<String, Object>> comlaintsCountsList = statMapper.getComlaintsCount(statDto);
        //药物收入
        List<Map<String, Object>> medicationCostsList = statMapper.getMedicationCosts(statDto);
        //检查收入
        List<Map<String, Object>> consultationFeeList = statMapper.getConsultationFee(statDto);
        //挂号费
        List<Map<String, Object>> registrationFeeList = statMapper.getRegistrationFee(statDto);
        
        // 转换List<Map>为Map方便后续处理
        Map<Long, Integer> totalRegistrations = new HashMap<>();
        for (Map<String, Object> map : totalRegistrationsList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Integer count = ((Number) map.get("totalRegistrations")).intValue();
            totalRegistrations.put(deptId, count);
        }
        
        Map<Long, Integer> cancellations = new HashMap<>();
        for (Map<String, Object> map : cancellationsList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Integer count = ((Number) map.get("totalRegistrations")).intValue();
            cancellations.put(deptId, count);
        }
        
        Map<String, Integer> aiConsultCounts = new HashMap<>();
        for (Map<String, Object> map : aiConsultCountsList) {
            String dept = (String) map.get("department");
            Integer count = ((Number) map.get("aiConsultCount")).intValue();
            aiConsultCounts.put(dept, count);
        }
        
        Map<Long, Integer> totalConsultCounts = new HashMap<>();
        for (Map<String, Object> map : totalConsultCountsList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Integer count = ((Number) map.get("totalConsultCount")).intValue();
            totalConsultCounts.put(deptId, count);
        }
        
        Map<String, Integer> aiDiagnosisAcceptance = new HashMap<>();
        for (Map<String, Object> map : aiDiagnosisAcceptanceList) {
            String dept = (String) map.get("department");
            Integer count = ((Number) map.get("aiConsultCount")).intValue();
            aiDiagnosisAcceptance.put(dept, count);
        }
        
        Map<Long, Integer> comlaintsCounts = new HashMap<>();
        for (Map<String, Object> map : comlaintsCountsList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Integer count = ((Number) map.get("complaintCount")).intValue();
            comlaintsCounts.put(deptId, count);
        }
        
        Map<Long, Double> medicationCosts = new HashMap<>();
        for (Map<String, Object> map : medicationCostsList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Double cost = ((Number) map.get("medicationCost")).doubleValue();
            medicationCosts.put(deptId, cost);
        }
        
        Map<Long, Double> consultationFee = new HashMap<>();
        for (Map<String, Object> map : consultationFeeList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Double fee = ((Number) map.get("consultationFee")).doubleValue();
            consultationFee.put(deptId, fee);
        }
        
        Map<Long, Double> registrationFee = new HashMap<>();
        for (Map<String, Object> map : registrationFeeList) {
            Long deptId = ((Number) map.get("departmentId")).longValue();
            Double fee = ((Number) map.get("registrationFee")).doubleValue();
            registrationFee.put(deptId, fee);
        }
        
        List<StatVo> statVos = new ArrayList<>();
        for (Map.Entry<Long,Integer> entry:totalRegistrations.entrySet()){
            Long departmentId = entry.getKey();
            StatVo statVo = new StatVo();
            statVo.setDepartmentId(departmentId);
            statVo.setDepartment(statMapper.getDepartmentNameById(departmentId));
            statVo.setTotalRegistrations(entry.getValue());
            statVo.setStatStartTime(statDto.getStatStartTime());
            statVo.setStatEndTime(statDto.getStatEndTime());
            statVo.setCreateTime(LocalDateTime.now());
            //退号患者数
            Integer cancellationCount = cancellations.getOrDefault(departmentId, 0);
            statVo.setCancellations(cancellationCount);
            //退号率
            if (entry.getValue() != 0 && cancellationCount != 0){
                double cancellationsRation = (double) cancellationCount / entry.getValue();
                statVo.setCancellationsRation(BigDecimal.valueOf(cancellationsRation)
                        .setScale(2, RoundingMode.HALF_UP).doubleValue());
            }else {
                statVo.setCancellationsRation(0.0);
            }
            //Ai问诊覆盖率
           String department = statMapper.getDepartmentNameById(departmentId);
            if(totalConsultCounts.getOrDefault(departmentId,0) != 0 && aiConsultCounts.getOrDefault(department,0) != 0){
                double aiConsultCoveragePct = (double) aiConsultCounts.getOrDefault(department,0) / totalConsultCounts.getOrDefault(departmentId,0);
                statVo.setAiConsultCoveragePct(BigDecimal.valueOf(aiConsultCoveragePct)
                        .setScale(2, RoundingMode.HALF_UP).doubleValue());
            }else {
                statVo.setAiConsultCoveragePct(0.0);
            }
            //医生采纳ai诊断建议的比例
            if(aiConsultCounts.getOrDefault(department,0) != 0 && aiDiagnosisAcceptance.getOrDefault(department,0) != 0){
                double aiDiagnosisAcceptancePct = (double) aiDiagnosisAcceptance.getOrDefault(department,0) / aiConsultCounts.getOrDefault(department,0);
                statVo.setAiDiagnosisAcceptancePct(BigDecimal.valueOf(aiDiagnosisAcceptancePct)
                        .setScale(2, RoundingMode.HALF_UP).doubleValue());
            }else {
                statVo.setAiDiagnosisAcceptancePct(0.0);
            }
            //患者投诉总数
            statVo.setComlaintsCount(comlaintsCounts.getOrDefault(departmentId,0));
            //投诉比例
            if(totalRegistrations.getOrDefault(departmentId,0) != 0 && comlaintsCounts.getOrDefault(departmentId,0) != 0){
                double comlaintsPct = (double) comlaintsCounts.getOrDefault(departmentId,0) / totalRegistrations.getOrDefault(departmentId,0);
                statVo.setComlatinsPct(BigDecimal.valueOf(comlaintsPct)
                        .setScale(2, RoundingMode.HALF_UP).doubleValue());
            }
            //总收入
            double outpatientRevenue = medicationCosts.getOrDefault(departmentId,0D) + consultationFee.getOrDefault(departmentId,0D) + registrationFee.getOrDefault(departmentId,0D);
            statVo.setOutpatientRevenue(outpatientRevenue);
            //药物收入占比
            if (outpatientRevenue != 0 && medicationCosts.getOrDefault(departmentId,0D) != 0){
                double drugRevenueRatio = medicationCosts.getOrDefault(departmentId,0D) / outpatientRevenue;
                statVo.setDrugRevenueRatio(BigDecimal.valueOf(drugRevenueRatio)
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue());
            }else {
                statVo.setDrugRevenueRatio(0D);
            }

            //检查收入占比
            if (outpatientRevenue != 0D && consultationFee.getOrDefault(departmentId, 0D) != 0D) {
                double testRevenueRatio = consultationFee.getOrDefault(departmentId,0D) / outpatientRevenue;
                statVo.setTestRevenueRatio(BigDecimal.valueOf(testRevenueRatio)
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue());
            }else {
                statVo.setTestRevenueRatio(0D);
            }
            statVos.add(statVo);
           statMapper.addStat(statVo);
        }
    }

    @Override
    public void allDoctorStat(DoctorStatDto doctorStatDto) {
        //根据科室id查询医生id,姓名,科室id,科室名称
        List<DoctorStatVo> doctorStatVos = statMapper.getDoctorAndDepartmentByDepartmentId(doctorStatDto.getDepartmentId());
        for (DoctorStatVo doctorStatVo : doctorStatVos) {
            doctorStatVo.setStatStartTime(doctorStatDto.getStatStartTime());
            doctorStatVo.setStatEndTime(doctorStatDto.getStatEndTime());
            //接待人次
            Integer totalConsultations = statMapper.getTotalConsultCounts(doctorStatVo.getDoctorId(),doctorStatDto);
            doctorStatVo.setTotalConsultations(totalConsultations);
            //医药费
            Double medicationCostsObj = statMapper.getMedicationCostses(doctorStatDto,doctorStatVo.getDoctorId());
            double medicationCosts = (medicationCostsObj != null) ? medicationCostsObj : 0.0;
            //检查费
            Double consultationFeeObj  = statMapper.getConsultationFees(doctorStatDto,doctorStatVo.getDoctorId());
            double consultationFee = (consultationFeeObj != null) ? consultationFeeObj : 0.0;
            //挂号费
            Double registrationFeeObj = statMapper.getRegistrationFees(doctorStatDto,doctorStatVo.getDoctorId());
            double registrationFee = (registrationFeeObj != null) ? registrationFeeObj : 0.0;
            //总费用
            double totalRevenue = medicationCosts + consultationFee + registrationFee;
            doctorStatVo.setTotalRevenue(totalRevenue);
            //医药费比例
            if (totalRevenue != 0 && medicationCosts != 0){
                double drugRevenueRatio = medicationCosts / totalRevenue;
                doctorStatVo.setDrugRevenueRatio(BigDecimal.valueOf(drugRevenueRatio)
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue());
            }else{
                doctorStatVo.setDrugRevenueRatio(0D);
            }
            //检查费比例
            if (totalRevenue != 0 && consultationFee != 0){
                double testRevenueRatio = consultationFee / totalRevenue;
                doctorStatVo.setTestRevenueRatio(BigDecimal.valueOf(testRevenueRatio)
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue());
            }else{
                doctorStatVo.setTestRevenueRatio(0D);
            }
            //线上患者满意度
            Double onlineSatisfactionScoreObj = statMapper.getOnlineSatisfactionScore(doctorStatDto,doctorStatVo.getDoctorId());
            double onlineSatisfactionScore = (onlineSatisfactionScoreObj != null) ? onlineSatisfactionScoreObj : 0.0;
            doctorStatVo.setOnlineSatisfactionScore(onlineSatisfactionScore);
            //正常出勤数
            Integer normalAttendance = statMapper.getNormalAttendance(doctorStatDto,doctorStatVo.getDoctorId());
            //总出勤数
            Integer totalAttendance = statMapper.getTotalAttendance(doctorStatDto,doctorStatVo.getDoctorId());
            //考勤率
            if (totalAttendance != 0 && normalAttendance != 0){
                double attendanceRate = normalAttendance.doubleValue()/totalAttendance;
                doctorStatVo.setAttendanceRate(BigDecimal.valueOf(attendanceRate)
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue());
            }else {
                doctorStatVo.setAttendanceRate(0D);
            }
            //水平评估分数
            double levelAssessmentScore = (doctorStatVo.getDrugRevenueRatio() * caseConfigProperties.getLevelAssessment().getMedicine()
                    + doctorStatVo.getTestRevenueRatio() * caseConfigProperties.getLevelAssessment().getCheck()
                    + doctorStatVo.getOnlineSatisfactionScore() * caseConfigProperties.getLevelAssessment().getSatisfaction()
                    + doctorStatVo.getAttendanceRate() * caseConfigProperties.getLevelAssessment().getAttendance())
                    * 100;
            doctorStatVo.setLevelAssessmentScore(BigDecimal.valueOf(levelAssessmentScore)
                    .setScale(2, RoundingMode.HALF_UP)
                    .doubleValue());
            //水平评估等级
            if (doctorStatVo.getLevelAssessmentScore() >= 85){
                doctorStatVo.setLevelAssessment("优秀");
            }else if (doctorStatVo.getLevelAssessmentScore() >= 70){
                doctorStatVo.setLevelAssessment("达标");
            }else {
                doctorStatVo.setLevelAssessment("需改进");
            }
            statMapper.addDoctorStat(doctorStatVo);
        }
    }

    /**
     * 执行月度统计任务，在每月最后一天执行
     */
    @Override
    @Scheduled(cron = "00 00 23 L * ?") // 每月最后一天的凌晨23点执行
    public void performMonthlyStatistics() {
        // 计算当前月的时间范围
        LocalDate now = LocalDate.now();
        LocalDateTime startTime = now.withDayOfMonth(1)  // 当前月的第一天
                .atTime(LocalTime.MIN);  // 00:00:00

        LocalDateTime endTime = now.withDayOfMonth(now.lengthOfMonth())  // 当前月的最后一天
                .atTime(23,59,59);  // 23:59:59

        // 执行科室统计
        StatDto statDto = new StatDto();
        statDto.setStatStartTime(startTime);
        statDto.setStatEndTime(endTime);
        allStat(statDto);

        // 执行医生统计（统计所有科室）
        DoctorStatDto doctorStatDto = new DoctorStatDto();
        doctorStatDto.setDepartmentId(0L); // 0表示所有科室
        doctorStatDto.setStatStartTime(startTime);
        doctorStatDto.setStatEndTime(endTime);
        allDoctorStat(doctorStatDto);
    }

    @Override
    public List<StatVo> getStat(LocalDateTime month) {
        return statMapper.getStat(month);
    }

    @Override
    public List<DoctorStatVo> getDoctorStat(LocalDateTime month, Long departmentId) {
        return statMapper.getDoctorStat(month,departmentId);
    }
}
